﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Options;
using WxLib.Core.Util;
using WxLib.Core.Serializers;
using WxLib.Core.RequestHandlers;
using WxLib.Common;
using WxLib.Business;

namespace WxLib.Business
{
    /// <summary>
    /// 企业付款到银行卡接口实现
    /// </summary>
    public class PayToBank
    {
        private string defaultUri = "https://api.mch.weixin.qq.com";
        private readonly WxApiOptions options;

        /// <summary>
        /// 构造函数
        /// </summary>
        public PayToBank(IOptions<WxApiOptions> optionsAccessor)
        {
            BaseUri = new Uri(defaultUri);
            RequestHandler = new RequestHandler(new XmlSerializer());
            options = optionsAccessor.Value;
        }


        /// <summary>
        /// 获取或设置用于执行请求的RequestHandler
        /// </summary>
        public IPostRequestHandler RequestHandler;

        /// <summary>
        /// 获取或设置请求的基本URI。
        /// </summary>
        public Uri BaseUri { get; set; }

        /// <summary>
        /// 企业付款到银行卡(异步)
        /// </summary>
        /// <param name="partner_trade_no">店面企业付款单号</param>
        /// <param name="enc_bank_no">收款方银行卡号</param>
        /// <param name="enc_true_name">收款方用户名</param>
        /// <param name="bank_code">收款方开户行</param>
        /// <param name="amount">付款金额(RMB:分)</param>
        /// <param name="desc">付款说明</param>
        /// <returns></returns>
        public Task<PayToBankResponse> PayAsync(string partner_trade_no, string enc_bank_no, string enc_true_name, BankCode bank_code, int amount, string desc)
        {
            var relUri = "/mmpaysptrans/pay_bank";
            PayToBankOptions payToBankOptions = new PayToBankOptions();
            payToBankOptions.mch_id = options.MchId;
            payToBankOptions.partner_trade_no = partner_trade_no;
            payToBankOptions.nonce_str = WxUtil.GetNoncestr();
            payToBankOptions.enc_bank_no = enc_bank_no;
            payToBankOptions.enc_true_name = enc_true_name;
            payToBankOptions.bank_code = ((int)bank_code).ToString();
            payToBankOptions.amount = amount;
            payToBankOptions.desc = desc;
            payToBankOptions.sign = WxUtil.GetSign<PayToBankOptions>(payToBankOptions, options.MchKey);
            var queryString = RequestHandler.Serializer.Serialize(payToBankOptions);
            return requestAsync<PayToBankResponse>(relUri, queryString);
        }

        /// <summary>
        /// 企业付款到银行卡
        /// </summary>
        /// <param name="partner_trade_no">店面企业付款单号</param>
        /// <param name="enc_bank_no">收款方银行卡号</param>
        /// <param name="enc_true_name">收款方用户名</param>
        /// <param name="bank_code">收款方开户行</param>
        /// <param name="amount">付款金额(RMB:分)</param>
        /// <param name="desc">付款说明</param>
        /// <returns></returns>
        public PayToBankResponse Pay(string partner_trade_no, string enc_bank_no, string enc_true_name, BankCode bank_code, int amount, string desc)
        {
            return PayAsync(partner_trade_no, enc_bank_no, enc_true_name, bank_code, amount, desc).Result;
        }

        /// <summary>
        /// 用于对店面企业付款到银行卡操作进行结果查询，返回付款操作详细结果。
        /// </summary>
        /// <param name="partner_trade_no">店面订单号，需保持唯一（只允许数字[0~9]或字母[A~Z]和[a~z]最短8位，最长32位）</param>
        /// <returns></returns>
        public Task<QueryPayToBankResponse> QueryAsync(string partner_trade_no)
        {
            var relUri = "/mmpaysptrans/query_bank";
            QueryPayToBankOptions queryPayToBankOptions = new QueryPayToBankOptions();
            queryPayToBankOptions.mch_id = options.MchId;
            queryPayToBankOptions.partner_trade_no = partner_trade_no;
            queryPayToBankOptions.nonce_str = WxUtil.GetNoncestr();
            queryPayToBankOptions.sign = WxUtil.GetSign<QueryPayToBankOptions>(queryPayToBankOptions, options.MchKey);
            var queryString = RequestHandler.Serializer.Serialize(queryPayToBankOptions);
            return requestAsync<QueryPayToBankResponse>(relUri, queryString);
        }

        /// <summary>
        /// 用于对店面企业付款到银行卡操作进行结果查询，返回付款操作详细结果。
        /// </summary>
        /// <param name="partner_trade_no">店面订单号，需保持唯一（只允许数字[0~9]或字母[A~Z]和[a~z]最短8位，最长32位）</param>
        /// <returns></returns>
        public QueryPayToBankResponse Query(string partner_trade_no)
        {
            return QueryAsync(partner_trade_no).Result;
        }

        /// <summary>
        /// 异步请求 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="relUri"></param>
        /// <param name="queryString"></param>
        /// <returns></returns>
        private async Task<T> requestAsync<T>(string relUri, string queryString)
        {
            return await RequestHandler.PostRequestAsync<T>(new Uri(BaseUri, relUri),
                    queryString, options.CertPath, options.CertPassWord).ConfigureAwait(false);
        }
    }
}
